package com.workshop.utils.check;
/**
 * 校验工具
 * @author chenwei
 * @date 2018年3月23日 下午4:34:14
 */

import java.io.ByteArrayInputStream;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.MemoryCacheImageInputStream;
import javax.naming.AuthenticationException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.util.TextUtils;

import com.workshop.utils.ResultMsg;

/**
 * 校验工具
 * 
 * @author 
 * @date 2018年3月23日 下午4:54:40
 */
public final class CheckUtil {
	/**
	 * 校验用户是否在线 不在线则抛异常 在线则继续执行代码
	 * <p>
	 * 备注:
	 * 此校验需要前端添加一个userkey的请求头参数,
	 * 参数值服务端返回给客户端用户数据的redis数据库的key
	 * </p>
	 * @author hexianli
	 * @date 2018年5月28日 上午11:54:22
	 * @param request
	 * @throws UserExpiredException
	 * @return user.class 的object
	 */
	public static Object checkOline(HttpServletRequest request) throws Exception {
		Object user = request.getAttribute(ResultMsg.USERTOKEN);
		if (user == null) {
			throw new AuthenticationException("登录失效,请重新登录!");
		}
		return user;
	}

	/**
	 * 校验是否是中文或者英文
	 * 
	 * @author chenwei
	 * @date 2018年3月24日 上午10:02:12
	 * @param str
	 * @param length
	 *            限定长度
	 * @return
	 */
	public static boolean checkChineseStr(String str, int length) {
		if (str == null) {
			return false;
		}
		if (str.equals("")) {
			return false;
		}
		// boolean matches = str.matches("[a-zA-Z\u4e00-\u9fa5]+");
		Pattern pattern = Pattern.compile("[a-zA-Z\u4e00-\u9fa5]");
		char c[] = str.toCharArray();
		for (int i = 0; i < length; i++) {
			if (i < c.length) {
				Matcher matcher = pattern.matcher(String.valueOf(c[i]));
				if (!matcher.matches()) {
					return false;
				}
			}
		}
		if (c.length > length) {
			return false;
		}
		return true;
	}

	/**
	 * 校验邮箱
	 * 
	 * @author chenwei
	 * @date 2018年3月24日 上午10:08:48
	 * @param emaile
	 * @return
	 */
	public static boolean checkEmaile(String emaile) {
		if (emaile == null) {
			return false;
		}
		String RULE_EMAIL = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";
		// 正则表达式的模式
		Pattern p = Pattern.compile(RULE_EMAIL);
		// 正则表达式的匹配器
		Matcher m = p.matcher(emaile);
		// 进行正则匹配
		return m.matches();
	}

	/**
	 * 校验密码
	 * 
	 * @author chenwei
	 * @date 2018年3月24日 上午10:13:18
	 * @param pwd
	 * @return
	 */
	public static boolean checkPwd(String pwd) {
		if (pwd == null) {
			return false;
		}
		if (pwd.equals("")) {
			return false;
		}
		if (!pwd.matches("[0-9a-zA-Z_%$]{6,16}")) {
			return false;
		}
		return true;
	}

	/**
	 * 校验身份证号
	 * 
	 * @author chenwei
	 * @date 2018年3月24日 上午10:14:46
	 * @param IDNumber
	 * @return
	 */
	public static boolean checkIDNumber(String IDNumber) {
		if (IDNumber == null || "".equals(IDNumber)) {
			return false;
		}
		// 定义判别用户身份证号的正则表达式（15位或者18位，最后一位可以为字母）
		String regularExpression = "(^[1-9]\\d{5}[1-9]{1}\\d{3}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|"
				+ "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
		// 假设18位身份证号码:41000119910101123X 410001 19910101 123X
		// ^开头
		// [1-9] 第一位1-9中的一个 4
		// \\d{5} 五位数字 10001（前六位省市县地区）
		// (18|19|20) 19（现阶段可能取值范围18xx-20xx年）
		// \\d{2} 91（年份）
		// ((0[1-9])|(10|11|12)) 01（月份）
		// (([0-2][1-9])|10|20|30|31)01（日期）
		// \\d{3} 三位数字 123（第十七位奇数代表男，偶数代表女）
		// [0-9Xx] 0123456789Xx其中的一个 X（第十八位为校验值）
		// $结尾

		// 假设15位身份证号码:410001910101123 410001 910101 123
		// ^开头
		// [1-9] 第一位1-9中的一个 4
		// \\d{5} 五位数字 10001（前六位省市县地区）
		// \\d{2} 91（年份）
		// ((0[1-9])|(10|11|12)) 01（月份）
		// (([0-2][1-9])|10|20|30|31)01（日期）
		// \\d{3} 三位数字 123（第十五位奇数代表男，偶数代表女），15位身份证不含X
		// $结尾

		boolean matches = IDNumber.matches(regularExpression);

		// 判断第18位校验值
		if (matches) {

			if (IDNumber.length() == 18) {
				try {
					char[] charArray = IDNumber.toCharArray();
					// 前十七位加权因子
					int[] idCardWi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
					// 这是除以11后，可能产生的11位余数对应的验证码
					String[] idCardY = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
					int sum = 0;
					for (int i = 0; i < idCardWi.length; i++) {
						int current = Integer.parseInt(String.valueOf(charArray[i]));
						int count = current * idCardWi[i];
						sum += count;
					}
					char idCardLast = charArray[17];
					int idCardMod = sum % 11;
					if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) {
						return true;
					} else {
						System.out.println("身份证最后一位:" + String.valueOf(idCardLast).toUpperCase() + "错误,正确的应该是:"
								+ idCardY[idCardMod].toUpperCase());
						return false;
					}

				} catch (Exception e) {
					e.printStackTrace();
					System.out.println("异常:" + IDNumber);
					return false;
				}
			}

		}
		return matches;
	}

	/**
	 * 校验图片类型 jpeg,jpg,png
	 * 
	 * @author chenwei
	 * @date 2018年3月26日 下午4:52:23
	 * @param imageBytes
	 *            文件字节数组
	 * @return boolean 类型不合法返回false 反之返回 true
	 * @throws Exception
	 */
	@SuppressWarnings("all")
	public static boolean checkImageType(byte[] imageBytes) throws Exception {
		ByteArrayInputStream bais = null;
		MemoryCacheImageInputStream mcis = null;
		try {
			bais = new ByteArrayInputStream(imageBytes);
			mcis = new MemoryCacheImageInputStream(bais);
			Iterator itr = ImageIO.getImageReaders(mcis);
			while (itr.hasNext()) {
				ImageReader reader = (ImageReader) itr.next();
				String imageName = reader.getClass().getSimpleName();
				if (imageName != null && ("JPEGImageReader".equalsIgnoreCase(imageName))) {
					return true;
				} else if (imageName != null && ("JPGImageReader".equalsIgnoreCase(imageName))) {
					return true;
				} else if (imageName != null && ("pngImageReader".equalsIgnoreCase(imageName))) {
					return true;
				}
			}
		} catch (Exception e) {
			throw new Exception();
		}
		return false;
	}

	
	/**
	 * 校验银行卡号
	 * 
	 * @author chenwei
	 * @date 2018年3月28日 下午8:17:19
	 * @param bankCard
	 * @return
	 */
	/*public static boolean checkBankCard(String bankCard) {
		if(!StringUtils.isNoneBlank(bankCard)) {
			return false;
		}
		if (bankCard.length() < 15 || bankCard.length() > 19) {
			return false;
		}
		char bit = getBankCardCheckCode(bankCard.substring(0, bankCard.length() - 1));
		if (bit == 'N') {
			return false;
		}
		return bankCard.charAt(bankCard.length() - 1) == bit;
	}*/
	/**
	 * 校验银行卡号
	 * 
	 * @author chenwei
	 * @date 2018年3月28日 下午8:17:19
	 * @param bankCard
	 * @return
	 */
	public static boolean checkBankCard(String bankCard) {
	    if (TextUtils.isEmpty(bankCard)) {
	        return false;
	    }
	    int[] cardNoArr = new int[bankCard.length()];
	    for (int i = 0; i < bankCard.length(); i++) {
	        cardNoArr[i] = Integer.valueOf(String.valueOf(bankCard.charAt(i)));
	    }
	    for (int i = cardNoArr.length - 2; i >= 0; i -= 2) {
	        cardNoArr[i] <<= 1;
	        cardNoArr[i] = cardNoArr[i] / 10 + cardNoArr[i] % 10;
	    }
	    int sum = 0;
	    for (int i = 0; i < cardNoArr.length; i++) {
	        sum += cardNoArr[i];
	    }
	    return sum % 10 == 0;
	}

	/**
	 * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
	 * @deprecated 作废了,部分银行卡无法校验成功
	 * @param nonCheckCodeBankCard
	 * @return
	 */
	@Deprecated
	@SuppressWarnings("all")
	private static char getBankCardCheckCode(String nonCheckCodeBankCard) {
		if (nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
				|| !nonCheckCodeBankCard.matches("\\d+")) {
			// 如果传的不是数据返回N
			return 'N';
		}
		char[] chs = nonCheckCodeBankCard.trim().toCharArray();
		int luhmSum = 0;
		for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
			int k = chs[i] - '0';
			if (j % 2 == 0) {
				k *= 2;
				k = k / 10 + k % 10;
			}
			luhmSum += k;
		}
		return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
	}
	/**
	 * 校验是否是文件名
	 * 
	 * @author chenwei
	 * @date 2018年3月30日 上午11:45:46
	 * @param fileName
	 * @return
	 */
	public static boolean checkFileName(String fileName){
		if(fileName==null || fileName!=null && fileName.length()==0) {
			return false;
		}
		if(!fileName.matches("^[0-9a-zA-Z]+\\.{1}[a-zA-Z]+$")) {
			return false;
		}
		return true;
	}
	
	/**
	 * 校验手机号
	 * 
	 * @author chenwei
	 * @date 2018年4月14日 上午11:39:58
	 * @param mobile 移动、联通、电信运营商的号码段  
	 * <p>移动的号段：134(0-8)、135、136、137、138、139、147（预计用于TD上网卡）  
     *、150、151、152、157（TD专用）、158、159、187（未启用）、188（TD专用）</p>  
     *<p>联通的号段：130、131、132、155、156（世界风专用）、185（未启用）、186（3g）</p>  
     *<p>电信的号段：133、153、180、177、173（未启用）、189</p>
     *<p>预防会增加的号段：16、19</p>    
	 * @return
	 */
	public static boolean checkMobile(String mobile){  
        String regex = "(\\+\\d+)?1[3456789]\\d{9}$";    
        return Pattern.matches(regex, mobile);  
    }  
	
	/**
	 * 区号+座机号码+分机号码 
	 * 
	 * @author chenwei
	 * @date 2018年4月14日 上午11:43:26
	 * @param fixedPhone
	 * @return
	 */
    public static boolean checkFixedPhone(String fixedPhone){  
        String reg="(?:(\\(\\+?86\\))(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)|" +  
                "(?:(86-?)?(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)";  
        return Pattern.matches(reg, fixedPhone);  
    }  
    
    /**
     * 电话号码验证
     * @author gujiahua
     * 2018年12月27日 上午10:22:39
     * @param str
     * @return
     */
    public static boolean checkPhone(final String str) {
        String phone1 = "^[0][0-9]{2,3}-[0-9]{5,10}$",// 验证带区号的
        		phone2 = "^[1-9]{1}[0-9]{5,8}$";// 验证没有区号的
        boolean b = false;       
        if (str.length() > 9) {
           b = Pattern.matches(phone1, str);
        } else {
           b = Pattern.matches(phone2, str);
        }
        return b;
    }
    
    /**
     * 匹配中国邮政编码  
     * 
     * @author chenwei
     * @date 2018年4月14日 上午11:44:44
     * @param postCode
     * @return
     */
    public static boolean checkPostCode(String postCode){  
        String reg = "[1-9]\\d{5}";  
        return Pattern.matches(reg, postCode);  
    }  
    /**
     * 金额验证  
     * 
     * @author chenwei
     * @date 2018年4月14日 上午11:44:44
     * @param postCode
     * @return
     */
    public static boolean checkMoney(String money){
    	 if(!StringUtils.isNotBlank(money)) {
    		 return false;   
    	 }
         Pattern pattern=Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$"); // 判断小数点后2位的数字的正则表达式  
         Matcher match=pattern.matcher(money);   
         if(match.matches()==false){   
            return false;   
         }else{   
            return true;   
         }   
     }  
    /**
     * 校验日期字符串格式 yyyy-MM-dd
     * @param str
     * @return
     */
    public static boolean checkDate(String str) {
		boolean convertSuccess = true;
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		try {
			format.setLenient(false);
			format.parse(str);
		} catch (Exception e) {
			convertSuccess = false;
		}
		return convertSuccess;
	}
    /**
     * 校验日期字符串格式 yyyy-MM-dd HH:mm:ss
     * @param str
     * @return
     */
    public static boolean checkDate2(String str) {
    	boolean convertSuccess = true;
    	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	try {
    		format.setLenient(false);
    		format.parse(str);
    	} catch (Exception e) {
    		convertSuccess = false;
    	}
    	return convertSuccess;
    }
    /**
     * 校验是否是正确的url地址
     * 判断http,https,ftp打头
     * @author chenwei
     * @date 2018年5月3日 上午10:53:58
     * @param url
     * @return
     */
    public static boolean checkUrl(String url) {
    	if(!StringUtils.isNotBlank(url)) {
    		return false;
    	}
		String regex = "^([hH][tT]{2}[pP]:/*|[hH][tT]{2}[pP][sS]:/*|[fF][tT][pP]:/*)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+(\\?{0,1}(([A-Za-z0-9-~]+\\={0,1})([A-Za-z0-9-~]*)\\&{0,1})*)$";
		Pattern pattern = Pattern.compile(regex);
		if (pattern.matcher(url).matches()) {
			return true;
		} else {
			return false;
		}
	}
    
    /**
     * 校验字符串是否为数字
     * @author lianglie
     * @date 2018年12月5日 下午7:41:41
     * @param str
     * @return
     */
    public static boolean isInteger(String str) {  
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");  
        return pattern.matcher(str).matches();  
    }
    /**
     * 校验是否能将字符串转数值
     * @author chenluqiang
     * @date 2018年12月5日 下午3:01:58 
     * @param str
     * @return
     */
    public static boolean checkIsNumber(String str) {
    	if(!StringUtils.isNotBlank(str)) {
    		return false;
    	}
    	try {
    		Long.parseLong(str);
    		return true;
    	}catch (Exception e) {
    		return false;
    	}
    }
    
    /**
     * 校验是否是26位中的单个字母，
     * @author chenluqiang
     * @date 2018年12月8日 下午2:40:33 
     * @param letter  字母
     * @param len 限制长度
     */
    public static boolean checkIsOneLetter(String letter,int len) {
    	if(!StringUtils.isNotBlank(letter)) {
    		return false;
    	}
    	if(letter.length()>len) {
    		return false;
    	}
		//检验输入的数据是否都为字母
		if (letter.matches("[a-zA-Z]+")) {
			return true;
		}else {
			return false;
		}
    }
    /**
     * 校验str是否符合正则表达式regEx
     * @author helo
     * @date 2019年1月5日下午4:59:06
     * @param regEx 正则表达式字符串
     * @param str 要匹配的字符串
     * @return
     */
    public static boolean checkMatch(String regEx,String str) {
    	Pattern pattern =Pattern.compile(regEx);
		Matcher matcher = pattern.matcher(str);
    	return matcher.matches();
    }
    
    /**
     * 校验经纬度是否合法
     *
     * @author lianglie
     * @date 2019年2月28日 下午2:38:49
     * @param coordinate
     * @return
     */
    public static boolean checkCoordinate(String coordinate) {
    	if(coordinate==null||"".equals(coordinate)||!coordinate.contains(",")) {
    		return false;
    	}
    	//经度
    	String regexLongitude = "[\\-+]?(0?\\d{1,2}|0?\\d{1,2}\\.\\d{1,15}|1[0-7]?\\d|1[0-7]?\\d\\.\\d{1,15}|180|180\\.0{1,15})";
		//纬度
    	String regexLatitude = "[\\-+]?([0-8]?\\d|[0-8]?\\d\\.\\d{1,15}|90|90\\.0{1,15})";
    	String[] data = coordinate.split(",");
		String longitude = data[0].trim();
		String latitude = data[1].trim();
		if(longitude.matches(regexLongitude) && latitude.matches(regexLatitude)) {
			return true;
		}
		return false;
	}
    
    
    
    
    
}
